# coding=utf-8

import datetime, uuid
from werkzeug.security import generate_password_hash, check_password_hash

from . import db, admin
from flask_admin.contrib.sqla import ModelView


# ModelView配置属性
class MicroBlogModelView(ModelView):
    can_create = False
    # can_delete = False  # disable model deletion
    page_size = 50  # the number of entries to display on the list view
    column_searchable_list = ['name', 'alias']  # 搜索字段
    column_filters = ['status']  # 过滤字段


class User(db.Model):
    __tablename__ = "users"
    id = db.Column(db.Integer, primary_key=True)
    # en name
    name = db.Column(db.String(64), unique=True, index=True)
    # zh name
    alias = db.Column(db.String(64), unique=False, nullable=True, index=True)
    ctime = db.Column(db.DateTime(timezone=True), nullable=False, default=datetime.datetime.now, index=True)
    email = db.Column(db.String(64), unique=False, nullable=True)
    group_id = db.Column(db.Integer, db.ForeignKey('groups.id'))
    status = db.Column(db.Boolean, nullable=False, default=True)
    password_hash = db.Column(db.String(128), nullable=True)
    lastchange = db.Column(db.DateTime(timezone=True), nullable=True, default=datetime.datetime.now, \
                            onupdate=datetime.datetime.now)

    @property
    def password(self):
        raise AttributeError('self.password is unreadable.')

    @password.setter
    def password(self, pwd):
        self.password_hash = generate_password_hash(pwd)

    @property
    def is_active(self):
        return self.status

    @property
    def is_authenticated(self):
        return True

    @property
    def is_anonymous(self):
        return False

    def verify_password(self, pwd):
        if self.password_hash:
            return check_password_hash(self.password_hash, pwd)
        else:
            return False
        #

    def get_id(self):
        return unicode(self.id)

    def __repr__(self):
        return "<User %r>" %self.name


class Group(db.Model):
    __tablename__ = "groups"
    id = db.Column(db.Integer, primary_key=True)
    # en name
    name = db.Column(db.String(64), unique=True)
    # zh name
    alias = db.Column(db.String(128), unique=True)
    status = db.Column(db.Boolean, default=True)
    ctime = db.Column(db.DateTime(timezone=True), nullable=False, default=datetime.datetime.now, index=True)
    level = db.Column(db.Integer, nullable=False, unique=False, default=0)
    detail = db.Column(db.Text(256), nullable=True)
    users = db.relationship('User', backref='the_group', lazy='dynamic')
    dutys = db.relationship('Duty', backref='the_group', lazy='dynamic')
    richtemp = db.relationship('TempText', backref='the_group', uselist=False)

    def add_user(self, user_name):
        pro_append_user = User.query.fileter_by(name=str(user_name)).first()
        if pro_append_user:
            self.users.append(pro_append_user)
            return True
        else:
            return False
        #

    def remove_user(self, user_name):
        pro_remove_user = User.query.fileter_by(name=str(user_name)).first()
        if pro_remove_user:
            self.users.remove(pro_remove_user)
            return True
        else:
            return False
        #

    def add_duty(self, duty_id):
        pro_append_duty = Duty.query.fileter_by(id=int(duty_id)).first()
        if pro_append_duty:
            self.dutys.append(pro_append_duty)
            return True
        else:
            return False
        #

    def remove_duty(self, duty_id):
        pro_remove_duty = Duty.query.fileter_by(id=int(duty_id)).first()
        if pro_remove_duty:
            self.dutys.remove(pro_remove_duty)
            return True
        else:
            return False
        #
    
    def __repr__(self):
        return "<Group %r>" %self.name


class Duty(db.Model):
    __tablename__ = 'duty'
    id = db.Column(db.Integer, primary_key=True, index=True)
    title = db.Column(db.String(128), nullable=False)
    # line-1->level=1; line-2->level=2; line-3->level=3
    level = db.Column(db.Integer, nullable=False, unique=False, default=2, index=True)
    ctime = db.Column(db.DateTime(timezone=True), nullable=False, default=datetime.datetime.now, index=True)
    time = db.Column(db.Date())
    status = db.Column(db.Boolean, default=True)
    rt = db.relationship('RichText', backref='the_duty', uselist=False)
    bws = db.relationship('BandWidth', backref='the_duty', lazy='dynamic')
    events = db.relationship('OPEvent', backref='the_duty', lazy='dynamic')
    group = db.Column(db.Integer, db.ForeignKey('groups.id'))
    dailyinfo = db.relationship('DailyInfo', backref='the_duty', uselist=False)
    lastchange = db.Column(db.DateTime(timezone=True), nullable=True, default=datetime.datetime.now, \
                            onupdate=datetime.datetime.now)

    def __repr__(self):
        return "<Duty %r>" %self.id


class DailyInfo(db.Model):
    __tablename__ = 'dailyinfo'
    id = db.Column(db.Integer, primary_key=True, index=True)
    line3 = db.Column(db.String(128), unique=False, nullable=True)
    line4 = db.Column(db.String(128), unique=False, nullable=True)
    ctime = db.Column(db.DateTime(timezone=True), default=datetime.datetime.now)
    time = db.Column(db.Date())
    status = db.Column(db.Boolean, default=True)
    explain = db.Column(db.Text, nullable=True)
    duty_id = db.Column(db.Integer, db.ForeignKey('duty.id'))
    lastchange = db.Column(db.DateTime(timezone=True), nullable=True, default=datetime.datetime.now, \
                            onupdate=datetime.datetime.now)

    def __repr__(self):
        return "<DailyInfo %r>" %self.id


class TempText(db.Model):
    __tablename__ = 'temptext'
    id = db.Column(db.Integer, primary_key=True, index=True)
    title = db.Column(db.String(128), nullable=False)
    type = db.Column(db.String(128), nullable=True)
    status = db.Column(db.Boolean, default=True)
    ctime = db.Column(db.DateTime(timezone=True), default=datetime.datetime.now)
    content = db.Column(db.Text, nullable=False)
    group_id = db.Column(db.Integer, db.ForeignKey('groups.id'))
    lastchange = db.Column(db.DateTime(timezone=True), nullable=True, default=datetime.datetime.now, \
                            onupdate=datetime.datetime.now)

    def __repr__(self):
        return "<TempText %r>" %self.id


class RichText(db.Model):
    __tablename__ = 'richtext'
    id = db.Column(db.Integer, primary_key=True, index=True)
    ctime = db.Column(db.DateTime(timezone=True), default=datetime.datetime.now)
    time = db.Column(db.Date())
    status = db.Column(db.Boolean, default=True)
    content = db.Column(db.Text, nullable=True)
    duty_id = db.Column(db.Integer, db.ForeignKey('duty.id'))
    pics = db.relationship('Picture', backref='the_richtext', lazy='dynamic')
    lastchange = db.Column(db.DateTime(timezone=True), nullable=True, default=datetime.datetime.now, \
                            onupdate=datetime.datetime.now)

    def __repr__(self):
        return "<RichText %r>" %self.id


class Picture(db.Model):
    __tablename__ = 'picture'            
    id = db.Column(db.Integer, primary_key=True, index=True)
    filename = db.Column(db.String(5000), nullable=False)
    ctime = db.Column(db.DateTime(timezone=True))
    filehash = db.Column(db.String(128), unique=True)
    richtext_id = db.Column(db.Integer, db.ForeignKey('richtext.id'))
    status = db.Column(db.Boolean, default=True)
    lastchange = db.Column(db.DateTime(timezone=True), nullable=True, default=datetime.datetime.now, \
                            onupdate=datetime.datetime.now)

    def __init__(self, name='',filehash=None):
        self.ctime = datetime.datetime.now()
        self.filehash = filehash if filehash else self._hash_name(name)
        self.filename = name if name else self.filehash

    @staticmethod
    def _hash_name(filename):
        _, _, suffix = filename.rpartition('.')
        return "%s.%s" %(uuid.uuid4().hex, suffix)

    def __repr__(self):
        return "<Picture %r>" %self.filehash


class BandWidth(db.Model):
    __tablename__ = 'bandwidth'        
    id = db.Column(db.Integer, primary_key=True, index=True)
    ctime = db.Column(db.DateTime(timezone=True), default=datetime.datetime.now, index=True)
    time = db.Column(db.Date())
    status = db.Column(db.Boolean, default=True)
    bw = db.Column(db.Float, nullable=False, default=0.0)
    duty_id = db.Column(db.Integer, db.ForeignKey('duty.id'))
    lastchange = db.Column(db.DateTime(timezone=True), nullable=True, default=datetime.datetime.now, \
                            onupdate=datetime.datetime.now)
    engineroom_id = db.Column(db.Integer,db.ForeignKey('engineroom.id'))

    def __repr__(self):
        return "<BandWidth %r>" %self.id


class OPEvent(db.Model):
    __tablename__ = 'opevent'
    id = db.Column(db.Integer, primary_key=True, index=True)
    ctime = db.Column(db.DateTime(timezone=True), nullable=False, default=datetime.datetime.now, index=True)
    # 精确到分
    time = db.Column(db.DateTime(timezone=True), nullable=True)
    level = db.Column(db.Integer, nullable=False, unique=False, default=2, index=True)
    status = db.Column(db.Boolean, default=True)
    title = db.Column(db.String(128), nullable=False)
    type = db.Column(db.String(128), nullable=False, index=True)
    content = db.Column(db.Text, nullable=False)
    response = db.Column(db.Text, nullable=True)
    duty_id = db.Column(db.Integer, db.ForeignKey('duty.id'))
    lastchange = db.Column(db.DateTime(timezone=True), nullable=True, default=datetime.datetime.now, \
                            onupdate=datetime.datetime.now)

    def __repr__(self):
        return "<OPEvent %r>" %self.id


class EngineRoom(db.Model):
    __tablename__ = 'engineroom'
    id = db.Column(db.Integer, primary_key=True, index=True)
    name = db.Column(db.String(64), unique=True)
    alias = db.Column(db.String(128), unique=False)
    ctime = db.Column(db.DateTime(timezone=True), default=datetime.datetime.now, index=True)
    status = db.Column(db.Boolean, default=True)
    script = db.Column(db.String(128), nullable=True)
    lastchange = db.Column(db.DateTime(timezone=True), nullable=True, default=datetime.datetime.now, \
                            onupdate=datetime.datetime.now)
    bands = db.relationship('BandWidth', backref='the_engineroom', lazy='dynamic')

    def __repr__(self):
        return "<EngineRoom %r>" %self.name


class Email(db.Model):
    __tablename__ = 'email'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, index=True)
    alias = db.Column(db.String(64), unique=False, nullable=True, index=True)
    status = db.Column(db.Boolean, default=True)
    ctime = db.Column(db.DateTime(timezone=True), nullable=False, default=datetime.datetime.now, index=True)
    address = db.Column(db.String(128), unique=False, nullable=True)
    lastchange = db.Column(db.DateTime(timezone=True), nullable=True, default=datetime.datetime.now, \
                            onupdate=datetime.datetime.now)

    def __repr__(self):
        return "<Email %r>" %self.name


class EmailStatus(db.Model):
    __tablename__ = 'emailstatus'
    id = db.Column(db.Integer, primary_key=True)
    ctime = db.Column(db.DateTime(timezone=True), nullable=False, default=datetime.datetime.now, index=True)
    status = db.Column(db.String(64), index=True, default=u'正在发送')
    uniquenum = db.Column(db.String(64), nullable=False)
    receiveaddress = db.Column(db.String(128), unique=False, nullable=True)

    def __repr__(self):
        return "<EmailStatus %r>" % self.status


admin.add_view(MicroBlogModelView(User, db.session))
admin.add_view(MicroBlogModelView(Group, db.session))
admin.add_view(ModelView(Duty, db.session))
admin.add_view(ModelView(DailyInfo, db.session))
admin.add_view(ModelView(TempText, db.session))
admin.add_view(ModelView(RichText, db.session))